/*
 * FindAnswer4.cpp
 * Created on: 28/03/2011
 * Author: catharine
 */
#include "FindAnswer4.h"

void verticalValues(int* verticalSizes, int* verticalInitial, IplImage* image,
		int vSize) {

	int height = image->height;
	int counter = 0;
	for (int x = 2; x < 6; x++) {
		for (int y = 2; y < height; y++) {
			int size = 0;
			if (cvGetReal2D(image, y, x) == 0) {
				if (counter < vSize) {
					verticalInitial[counter] = y;
				}

				while (true) {
					if (y < height - 1 && cvGetReal2D(image, y, x) == 0) {
						y++;
						size++;
					} else {
						break;
					}
				}

				if (counter < vSize) {
					verticalSizes[counter] = size;
				}
				counter++;
			}
		}
	}
}

void horizontalValues(int * horizontalSizes, int * horizontalInitial,
		IplImage * img, int hSize) {
	int width = img->width;
	int counter = 0;
	for (int y = 2; y < 6; y++) {
		for (int x = 2; x < width; x++) {
			int size = 0;
			if (cvGetReal2D(img, y, x) == 0) {
				if (counter < hSize) {
					horizontalInitial[counter] = x;
				}

				while (true) {
					if (x < width - 1 && cvGetReal2D(img, y, x) == 0) {
						x++;
						size++;
					} else {
						break;
					}
				}

				if (counter < hSize) {
					horizontalSizes[counter] = size;
				}
				counter++;
			}
		}
	}
}

double findNumberBlackPixels(IplImage* image, int height, int width) {
	double sum = 0;
	for (int i = 0; i < height; i++) {
		for (int j = 0; j < width; j++) {
			if (cvGetReal2D(image, i, j) == 0) {
				sum++;
			}
		}
	}
	return sum;
}

void findSumROI(double **sumROI, IplImage* image, int vSize, int hSize,
		int* horizontalInitial, int* horizontalSizes, int* verticalInitial,
		int* verticalSizes, int middle) {
	int delta = 1;
	for (int i = 0; i < hSize; i++) {
		for (int j = 0; j < vSize; j++) {
			int width = horizontalSizes[i] + delta;
			int height = verticalSizes[j] + delta;
			int x = horizontalInitial[i] - delta;
			int y = verticalInitial[j] - delta;

			stringstream s;
			cvSetImageROI(image, cvRect(x, y, width, height));
			if (j < middle) {
				sumROI[i][j] = findNumberBlackPixels(image, height, width);
			} else {
				sumROI[i + 16][j - 5] = findNumberBlackPixels(image, height,
						width);
			}

			cvResetImageROI(image);
		}
	}
}

void createArchieve(String name, string* array, int arraySize) {
	ofstream arquivo;
	arquivo.open(name.c_str());

	for (int i = 0; i < arraySize; i++) {
		arquivo << array[i] << endl;
	}
	arquivo.close();
}

void createArchieve(string name, string content) {
	ofstream arquivo;
	arquivo.open(name.c_str());
	arquivo << content;
	arquivo.close();
}

string findAnswer(double** sumROI, int doublee, int middle, double threshold1) {
	stringstream s;
	s << "";
	for (int i = 0; i < doublee; i++) {
		int lengthBefore = s.str().length();
		for (int j = 0; j < middle; j++) {
			int value = sumROI[i][j];
			if (j == 0 && value >= 90) {
				s << "A";
				break;
			}
			if (j == 1 && value >= 65) {
				s << "B";
				break;
			}
			if (j == 2 && value >= 85) {
				s << "C";
				break;
			}
			if (j == 3 && value >= 55) {
				s << "D";
				break;
			}
			if (j == 4 && value >= 70) {
				s << "E";
				break;
			}
		}
		int lengthAfter = s.str().length();
		if (lengthAfter == lengthBefore) {
			s << "V";
		}
	}
	return s.str();
}

string compareAnswers(const char * archieveFileName,
		const char * answerFileName) {
	ifstream archieve(archieveFileName);
	ifstream answer(answerFileName);

	string lineAnswer;
	string lineArchieve;
	string nameImageArchieve;
	string nameImageAnswer;
	int right = 0;
	int wrong = 0;

	stringstream a;
	a << "";
	while (true) {
		archieve >> nameImageArchieve >> lineArchieve;
		answer >> nameImageAnswer >> lineAnswer;

		if (archieve.eof() && answer.eof()) {
			break;
		}

		a << "Imagem: ";
		a << nameImageAnswer;
		a << "\n";

		if (lineAnswer.compare(lineArchieve) != 0) {
			int size = lineAnswer.size();
			a << "   Questões com erro. \n";

			for (int i = 0; i < size; i++) {
				if (lineAnswer[i] != lineArchieve[i]) {
					a << "      Encontrado: ";
					a << (i + 1);
					a << lineAnswer[i];
					a << ". ";

					a << "      Esperado: ";
					a << (i + 1);
					a << lineArchieve[i];
					a << ".\n";
					wrong++;
				} else {
					right++;
				}
			}
			a << "\n";
		} else {
			right += 32;
			a
					<< "    Respostas encontradas estão iguais às respostas esperadas. \n \n";
		}
	}

	int total = right + wrong;
	double hitRate = 100 * ((double) right / (double) total);
	double errorRate = 100 * ((double) wrong / (double) total);

	a << "\nTotal de questões avaliadas: " << total << "\n";
	a << "   Questões corretas: " << right << "\n";
	a << "   Questões erradas: " << wrong << "\n \n \n";

	a << "Taxa de acerto: " << hitRate << "%\n";
	a << "Taxa de erro: " << errorRate << "%\n";

	archieve.close();
	answer.close();
	return a.str();
}

string fileName(int i) {
	stringstream name;
	name << "Gabaritos/Gabarito" << i;
	return name.str();
}

int main(int argc, char **argv) {
	if (argc < 3) {
		cout << "Para que o programa esse executado corretamente insira"
				<< " os 3 dados necessarios." << endl;
		cout << "1º: Programa." << endl << "2º: Limiar." << endl;
		cout << "3º: O arquivo com o gabarito das marcações." << endl;

	} else {
		double threshold1 = atof(argv[1]);

		int numberDocuments = 4;
		string content;
		for (int i = 1; i <= numberDocuments; i++) {
			string picture = fileName(i);

			IplImage* image = cvLoadImage(picture.append("rotacionada.bmp").c_str());
			IplImage * imageGS = cvCreateImage(cvGetSize(image), 8, 1);
			IplImage * dst = cvCreateImage(cvGetSize(image), 8, 1);


			double percent = (770 / double(dst->width)) * 100;
			IplImage * dst2 = cvCreateImage(cvSize(
					(int) ((dst->width * percent) / 100), (int) ((dst->height
							* percent) / 100)), 8, 1);

			cvCvtColor(image, imageGS, CV_RGB2GRAY);

			const int hSize = 16;
			const int vSize = 10;
			const int doublee = hSize * 2;
			const int middle = vSize / 2;

			int* horizontalSizes = new int[hSize];
			int* horizontalInitial = new int[hSize];

			int* verticalSizes = new int[vSize];
			int* verticalInitial = new int[vSize];

			cvAdaptiveThreshold(imageGS, dst, 255, CV_ADAPTIVE_THRESH_MEAN_C,
					CV_THRESH_BINARY, 151, 5);

			cvResize(dst, dst2);

			horizontalValues(horizontalSizes, horizontalInitial, dst2, hSize);
			verticalValues(verticalSizes, verticalInitial, dst2, vSize);

			double ** sumROI = new double*[doublee];
			for (int i = 0; i < doublee; i++) {
				sumROI[i] = new double[middle];
			}

			findSumROI(sumROI, dst2, vSize, hSize, horizontalInitial,
					horizontalSizes, verticalInitial, verticalSizes, middle);

			content.append(picture);
			content.append(" ");
			content.append(findAnswer(sumROI, doublee, middle, threshold1));
			content.append("\n");

			cvReleaseImage(&image);
			cvReleaseImage(&imageGS);
			cvReleaseImage(&dst);
			cvReleaseImage(&dst2);
		}

	//	string file = "RespostasFind4.txt";
		//createArchieve(file, content);

//		string comparison;
	//	comparison.append(compareAnswers(argv[2], file.c_str()));

		//string newFile = "ComparacaoDasRespostasFind4.txt";
		//createArchieve(newFile, comparison);
	}
}
